/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.com.gruposicom.controller;

import ar.com.gruposicom.dao.CommandDao;
import ar.com.gruposicom.dao.OperationDao;
import ar.com.gruposicom.dao.PoliticDao;
import ar.com.gruposicom.dao.TrueValueDao;
import ar.com.gruposicom.dao.implement.CommandDaoImp;
import ar.com.gruposicom.dao.implement.OperationDaoImp;
import ar.com.gruposicom.dao.implement.PoliticDaoImp;
import ar.com.gruposicom.dao.implement.TrueValueDaoImp;
import ar.com.gruposicom.domain.Command;
import ar.com.gruposicom.domain.Operation;
import ar.com.gruposicom.domain.Politic;
import ar.com.gruposicom.domain.TrueValue;
import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTable;
import javax.swing.JTextArea;

/**
 *
 * @author marcelo
 */
public class OperationController implements SystemOut
{

    private Command command = new Command();
    private JTextArea salida;
    private JTable tableOperations;
    private AnalizerController analizerController;
    private Collection<Command> comands;
    private Collection<Politic> politics;
    private Collection<TrueValue> values;
    
    public OperationController() 
    {
    }
    
    public OperationController(JTextArea salida, AnalizerController analizerController, JTable tableOperations) 
    {
        this.salida = salida;
        this.analizerController = analizerController;
        this.tableOperations = tableOperations;
    }

    public Command getCommand() {
        return command;
    }

    public void setCommand(Command command) {
        this.command = command;
        this.analizerController.setCom(command);
    }

    public JTextArea getSalida() {
        return salida;
    }

    public void setSalida(JTextArea salida) {
        this.salida = salida;
    }
    
    
    
    public void testOperation(Command c)
    {
        ExecuteTest e = new ExecuteTest(c, this);
//        ExecuteCommand e = new ExecuteCommand(c, this);
        e.start();
    }

    @Override
    public void append(String text) 
    {
        salida.append(text);
        salida.append(System.getProperty("line.separator"));
    }
    
    public void newOperation(Operation o)
    {
        
    }
    
    public Collection<Operation> getAll()
    {
        OperationDao sql = new OperationDaoImp();
        Collection<Operation> co = sql.getAll();
        Collection<Operation> temp = new ArrayList<>();
        if(co == null)
        {
            temp = this.getOperationsFromCsv();
        }
        else
        {
            Iterator<Operation> it = co.iterator();
            while(it.hasNext())
            {
                Operation o = it.next();
                o.setCommand(this.getCommands(o.getId()));
                temp.add(o);
            }
            this.writeOperationCsv(temp);
        }
        
        return temp;
    }
    
    private Collection<Command> getCommands(int id)
    {
        CommandDao sql = new CommandDaoImp();
        Collection<Command> co = sql.getAllFromOperation(id);
        Collection<Command> temp = new ArrayList<>();
        Iterator<Command> it = co.iterator();
        while(it.hasNext())
        {
            Command c = it.next();
            c.setPolitics(this.getPolitics(c.getId()));
            temp.add(c);
        }
        return temp;
    }
    
    private Collection<Politic> getPolitics(int id)
    {
        PoliticDao sql = new PoliticDaoImp();
        Collection<Politic> politics = sql.getAllFromCommand(id);
        Collection<Politic> temp = new ArrayList<>();
        Iterator<Politic> it = politics.iterator();
        while(it.hasNext())
        {
            Politic p = it.next();
            p.setTrueValues(this.getValues(p.getId()));
            temp.add(p);
        }
        return temp;
    }
    
    private Collection<TrueValue> getValues(int id)
    {
        TrueValueDao sql = new TrueValueDaoImp();
        return sql.getAllFromPolitic(id);
    }
    
    
    ///////////////////////////////////////////////////
    
    
    public void saveOperation(Operation o)
    {
        OperationDao sql = new OperationDaoImp();
        int id = sql.save(o);
        if(id!=0)
            this.saveCommands(o.getCommand(), id);
        else
        {
            /*aqui se define el metodo para guardar la operacion en forma temporal hasta que
             * se reestablesca la conexion con la base de datos.
             */
        }
    }
    
    private void saveCommands(Collection<Command> commands, int id)
    {
        Iterator<Command> it = commands.iterator();
        CommandDao sql = new CommandDaoImp();
        while(it.hasNext())
        {
            Command c = it.next();
            System.out.println("Cantidad de politicas a ser guardadas: "+c.getPolitics().size());
            this.savePolitics(c.getPolitics(), sql.save(c, id));
        }
    }
    
    private void savePolitics(Collection<Politic> politics, int id)
    {
        Iterator<Politic> it = politics.iterator();
        PoliticDao sql = new PoliticDaoImp();
        while(it.hasNext())
        {
            Politic p = it.next();
            System.out.println("Cantidad de valores a ser guardados: "+p.getTrueValues().size());
            this.saveValues(p.getTrueValues(), sql.save(p, id));
        }
    }
    
    private void saveValues(Collection<TrueValue> values, int id)
    {
        Iterator<TrueValue> it = values.iterator();
        TrueValueDao sql = new TrueValueDaoImp();
        while(it.hasNext())
        {
            sql.save(it.next(), id);
        }
    }

    @Override
    public void setPoliticStatus(Politic p, String status) 
    {
        int id = p.getId();
        int rows = this.tableOperations.getRowCount();
        for (int i=0; i<rows; i++)
        {
            if(Integer.parseInt(String.valueOf(this.tableOperations.getValueAt(i, 0))) == id)
            {
                tableOperations.setValueAt(status, i, 2);
                break;
            }
        }
    }
    
    
    
    
    /////////////////////// parte csv -  registrar operaciones //////////////////////////
    
    private void writeOperationCsv(Collection<Operation> ops)
    {
        try {
            Iterator<Operation> it = ops.iterator();
            if(new File("Operaciones.csv").exists())
                new File("Operaciones.csv").delete();
            if(new File("Comandos.csv").exists())
                new File("Comandos.csv").delete();
            if(new File("Politicas.csv").exists())
                new File("Politicas.csv").delete();
            if(new File("ValoresCorrectos.csv").exists())
                new File("ValoresCorrectos.csv").delete();
            this.writeHeaders();
            CsvWriter w = new CsvWriter (new FileWriter("Operaciones.csv", true), ';');
    //        CsvWriter w = new CsvWriter ("Operaciones.csv");
    //        w.setDelimiter(';');
//            CsvWriter wComandos = new CsvWriter ("Comandos.csv");
//            wComandos.setDelimiter(';');
            CsvWriter wComandos = new CsvWriter (new FileWriter("Comandos.csv", true), ';');
            while(it.hasNext())
            {
                Operation o = it.next();
                try
                {
                    w.write(String.valueOf(o.getId()));
                    w.write(o.getName().trim());
                    w.endRecord();
                    this.writeCommandCsv(o.getCommand(), wComandos, o.getId());
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            w.close();
            wComandos.close();
        } catch (IOException ex) {
            Logger.getLogger(OperationController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void writeHeaders()
    {
        CsvWriter w = new CsvWriter ("Operaciones.csv");
        w.setDelimiter(';');
        CsvWriter wComandos = new CsvWriter ("Comandos.csv");
        wComandos.setDelimiter(';');
        CsvWriter wPoliticas = new CsvWriter ("Politicas.csv");
        wPoliticas.setDelimiter(';');
        CsvWriter wValores = new CsvWriter ("ValoresCorrectos.csv");
        wValores.setDelimiter(';');
        try
        {
            //operaciones
            w.write("id");
            w.write("nombre");
            w.endRecord();
             w.close();
            //comandos
            wComandos.write("id");
            wComandos.write("operacionId");
            wComandos.write("comando");
            wComandos.endRecord();
            wComandos.close();
            //politicas
            wPoliticas.write("id");
            wPoliticas.write("comandoId");
            wPoliticas.write("oracion");
            wPoliticas.write("objetivo");
            wPoliticas.write("cadenaInicio");
            wPoliticas.write("cadenaFin");
            wPoliticas.write("nombre");
            wPoliticas.endRecord();
            wPoliticas.close();
            //Valores correctos
            wValores.write("id");
            wValores.write("politicaId");
            wValores.write("valor");
            wValores.write("tipoDato");
            wValores.write("reglaComparacion");
            wValores.endRecord();
            wValores.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            //cerrando writers
           
            
            
            
        }
    }
    
    private void writeCommandCsv(Collection<Command> co, CsvWriter wComandos, int idOperation)
    {
        try {
            Iterator<Command> it = co.iterator();
            CsvWriter w = new CsvWriter (new FileWriter("Politicas.csv", true), ';');
    //        CsvWriter w = new CsvWriter ("Politicas.csv");
    //        w.setDelimiter(';');
            while(it.hasNext())
            {
                Command c = it.next();
                try
                {
                    wComandos.write(String.valueOf(c.getId()));
                    wComandos.write(String.valueOf(idOperation));
                    wComandos.write(c.getCommand());
                    wComandos.endRecord();
                    this.writePoliticsCsv(c.getPolitics(), w, c.getId());
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
    //        wComandos.close();
            w.close();
        } catch (IOException ex) {
            Logger.getLogger(OperationController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void writePoliticsCsv(Collection<Politic> co, CsvWriter w, int idCommand)
    {
        try {
            Iterator<Politic> it = co.iterator();
            CsvWriter w2 = new CsvWriter (new FileWriter("ValoresCorrectos.csv", true), ';');
    //        CsvWriter w2 = new CsvWriter ("ValoresCorrectos.csv");
            w2.setDelimiter(';');
            while(it.hasNext())
            {
                Politic p = it.next();
                try
                {
                    w.write(String.valueOf(p.getId()));
                    w.write(String.valueOf(idCommand));
                    w.write(p.getSentence());
                    w.write(p.getObjetive());
                    w.write(p.getInitString());
                    w.write(p.getEndString());
                    w.write(p.getName());
                    w.endRecord();
                    this.writeValuesCsv(p.getTrueValues(), w2, p.getId());
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
    //        w.close();
            w2.close();
        } catch (IOException ex) {
            Logger.getLogger(OperationController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    private void writeValuesCsv(Collection<TrueValue> co, CsvWriter w, int idPolitic)
    {
        Iterator<TrueValue> it = co.iterator();
//        CsvWriter w2 = new CsvWriter ("ValoresCorrectos.csv");
//        w2.setDelimiter(';');
        while(it.hasNext())
        {
            TrueValue t = it.next();
            try
            {
                w.write(String.valueOf(t.getId()));
                w.write(String.valueOf(idPolitic));
                w.write(t.getValue());
                w.write(t.getDataType());
                w.write(t.getRuleComparation());
                w.endRecord();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
//        w.close();
    }
    
    
    /////////////// Recuperar operaciones //////////////
    private Collection<Operation> getOperationsFromCsv()
    {
        Collection<Operation> ops = new ArrayList<>();
        this.loadCommands();
        this.loadPolitics();
        this.loadValues();
        try {
            CsvReader reader = new CsvReader("Operaciones.csv");
            reader.setDelimiter(';');
            reader.readHeaders();

            while (reader.readRecord())
            {
                Operation o = new Operation();
                System.out.println("Leyendo datos de operacion: "+reader.get("id"));
                o.setId(Integer.parseInt(reader.get("id")));
                o.setName(reader.get("nombre"));
                o.setCommand(this.getCommandsFromCsv(o.getId()));
                System.out.println("Se cargaron "+o.getCommand().size()+" comandos");
                ops.add(o);
            }
            reader.close();
            } catch (FileNotFoundException e) {
                    e.printStackTrace();
            } catch (IOException e) {
                    e.printStackTrace();
            }
        return ops;
    }
    
    private void loadCommands()
    {
        this.comands = new ArrayList<>();
        try 
        {
            CsvReader reader = new CsvReader("Comandos.csv");
            reader.setDelimiter(';');
            reader.readHeaders();

            while (reader.readRecord())
            {
                System.out.println("Leyendo: "+reader.get("id"));
                Command c = new Command();
                c.setId(Integer.valueOf(reader.get("id")));
                c.setIdOperation(Integer.parseInt(reader.get("operacionId")));
                c.setCommand(reader.get("comando"));
                this.comands.add(c);
            }
            reader.close();
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
    }
    
    private void loadPolitics()
    {
        this.politics = new ArrayList<>();
        try 
        {
            CsvReader reader = new CsvReader("Politicas.csv");
            reader.setDelimiter(';');
            reader.readHeaders();

            while (reader.readRecord())
            {
                Politic p = new Politic();
                p.setId(Integer.valueOf(reader.get("id")));
                p.setCommandId(Integer.parseInt(reader.get("comandoId")));
                p.setSentence(reader.get("oracion"));
                p.setObjetive(reader.get("objetivo"));
                p.setInitString(reader.get("cadenaInicio"));
                p.setEndString(reader.get("cadenaFin"));
                p.setName(reader.get("nombre"));
                this.politics.add(p);
            }
            reader.close();
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
        System.out.println("Se cargaron "+this.politics.size()+" elementos en la coleccion de politicas");
    }
    
    private void loadValues()
    {
        this.values = new ArrayList<>();
        try 
        {
            CsvReader reader = new CsvReader("ValoresCorrectos.csv");
            reader.setDelimiter(';');
            reader.readHeaders();

            while (reader.readRecord())
            {
                TrueValue t = new TrueValue();
                t.setId(Integer.valueOf(reader.get("id")));
                t.setPoliticaId(Integer.valueOf(reader.get("politicaId")));
                t.setValue(reader.get("valor"));
                t.setDataType(reader.get("tipoDato"));
                t.setRuleComparation(reader.get("reglaComparacion"));
                this.values.add(t);
            }
            reader.close();
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
    }
    
    private Collection<Command> getCommandsFromCsv(int idOperation)
    {
        Collection<Command> co = new ArrayList<>();
        Iterator<Command> it = this.comands.iterator();
        while(it.hasNext())
        {
            Command c = it.next();
            if(c.getIdOperation() == idOperation)
            {
                c.setPolitics(this.getPoliticsFromCsv(c.getId()));
                System.out.println("Se cargaron "+c.getPolitics().size()+" politicas al comando");
                co.add(c);
            }
                
        }
        return co;
    }
    
    private Collection<Politic> getPoliticsFromCsv(int idCommand)
    {
        Collection<Politic> co = new ArrayList<>();
        Iterator<Politic> it = this.politics.iterator();
        while(it.hasNext())
        {
            Politic p = it.next();
            System.out.println("El codigo de comando inserto en politica es "+p.getCommandId()+" y el codigo de comando recibido es: "+idCommand);
            if(p.getCommandId() == idCommand)
            {
                p.setTrueValues(this.getValuesFromCsv(p.getId()));
                co.add(p);
            }
        }
        return co;
    }
    
    private Collection<TrueValue> getValuesFromCsv(int idPolitic)
    {
        Collection<TrueValue> co = new ArrayList<>();
        Iterator<TrueValue> it = this.values.iterator();
        while(it.hasNext())
        {
            TrueValue t = it.next();
            if(t.getPoliticaId() == idPolitic)
                co.add(t);
        }
        return co;
    }
    
}
